#ifndef _PROCESS_COMPOSITION_H_
#define _PROCESS_COMPOSITION_H_

#include <Event.h>
#include <string>
#include <csp_shared_types.h>
#include <SpuProgram.h>




using namespace std;

class Alting;
class ProcessComposition;

typedef struct channel_link{
	ProcessComposition *process;
	ls_addr_t ls_addr;
	int return_value;
} channel_link_t;

class ProcessComposition{
	private:
		pcb_t *pcb;
		SpuProgram *spu_prgm;
		int last_spe_id;
		Event *event;
		ProcessComposition *parent;
		char *mnemonic;
		Alting *alt;


		int pcbIdx;

	public:
		ProcessComposition(string mnemonic, Event *event, ProcessComposition *parent);
		ProcessComposition(uint64_t mnemonic_hash, Event *event, ProcessComposition *parent);
		
		void Init(uint64_t hash, Event *event, ProcessComposition *parent);

		void Setup(unsigned char ls_mem_slot, uint32_t pid);
		void SetState(uint32_t state);
		int32_t GetPID(){return pcb->pid;}
		int32_t GetExitStatus(){return pcb->ret_val;}
		void SetExitStatus(int32_t status);
		uint32_t GetState();
		unsigned char GetMemorySlot();
		char* GetMnemonic(){return spu_prgm->GetMnemonic();}
		void SetLastSpeID(int spe_id){last_spe_id =spe_id;}
		int  GetLastSpeID(){return last_spe_id;}
		void SetMemorySlot(unsigned char slot);

		Alting *GetAlting(csp_channel_t* list, int size);

		int GetPCBIdx(){return pcbIdx;}
		pcb_t* GetPCB(){return pcb;}
		ea_addr_t GetEAStore(){return pcb->ea_store;}
		void ClearDMACompletionFlag();
		void WaitForDMACompletion(int pos, int spe_id);
		
		void SetEvent(Event* event_, ProcessComposition* parent_);
		Event* GetEvent(){return event;}
		void Schedule();
		void Add(ProcessComposition &component);
		void TriggerEvent(int status);

		void Print();

		int spid;

/*	
		#define HIST_SIZE 10
		int hist_idx;
		int history[HIST_SIZE];
		int history_spe[HIST_SIZE];

		void SetLast(int pos, int spe_id){
			history[hist_idx] = pos;
			history_spe[hist_idx] = spe_id;
			hist_idx = (hist_idx+1) % HIST_SIZE;
			}*/
		//int  GetLast(){return history[hist_idx];}

		channel_link_t channel_link;

		/* Queue */
		ProcessComposition *next;	
};


#endif
